package com.dxy.yzs.marathon.common.log.aop;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.dxy.yzs.marathon.common.log.annotation.LogAnnotation;
import com.dxy.yzs.marathon.common.log.model.SysLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * 日志AOP,标准日志格式logback-spring.xml
 * 如果开启日志记录，需要多数据配置
 */
@Configuration
@Slf4j
@Aspect
@Order(-1) // 保证该AOP在@Transactional之前执行
public class LogAnnotationAOP {

	@Around("@annotation(ds)")
	public Object logSave(ProceedingJoinPoint joinPoint, LogAnnotation ds) throws Throwable {

		// 记录开始时间
		long start = System.currentTimeMillis();
		// 获取方法参数
		String url = null;
		String httpMethod = null;
		Object result = null;
		List<Object> httpReqArgs = new ArrayList<Object>();
		SysLog sysLog = new SysLog();
		sysLog.setCreateTime(new Date());
        // 获取当前登录用户
        sysLog.setUsername("test");
		MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
		LogAnnotation logAnnotation = methodSignature.getMethod().getDeclaredAnnotation(LogAnnotation.class);
		sysLog.setModule(logAnnotation.module() + ":" + methodSignature.getDeclaringTypeName() + "/"
				+ methodSignature.getName());

		Object[] args = joinPoint.getArgs();// 参数值
		url =  methodSignature.getDeclaringTypeName() + "/"+ methodSignature.getName();
		String params = null ;
		for (Object object : args) {
			if (object instanceof HttpServletRequest) {
				HttpServletRequest request = (HttpServletRequest) object;
				url = request.getRequestURI();
				httpMethod = request.getMethod();
			} else if (object instanceof HttpServletResponse) {

			} else {

				httpReqArgs.add(object);
			}
		}

		try {
			params = JSONUtil.toJsonStr(httpReqArgs);
			sysLog.setParams(params);
			// 打印请求参数参数
			log.info("开始请求,  url={} , httpMethod={}, reqData={} ", url, httpMethod, params);
		} catch (Exception e) {
			log.error("记录参数失败：{}", e.getMessage());
		}

		try {
			// 调用原来的方法
			result = joinPoint.proceed();
			sysLog.setFlag(Boolean.TRUE);
		} catch (Exception e) {
			sysLog.setFlag(Boolean.FALSE);
			sysLog.setRemark(e.getMessage());
			log.error("请求报错， url={} , httpMethod={}, reqData={} ,error ={} ",  url, httpMethod, params,e.getMessage());
			throw e;
		} finally {
		    log.info("本次操作日志为: {}", JSONUtil.toJsonStr(sysLog));
			// 获取回执报文及耗时
			log.info("请求完成, 耗时= {} ms", (System.currentTimeMillis() - start));
		}
		return result;
	}

}
